﻿#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/sync/interprocess_condition.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <boost/unordered_map.hpp>
#include <functional>                    //std::equal_to
#include <boost/container_hash/hash.hpp> //boost::hash

using namespace boost::multi_index;

class custom_data
{
public:
    struct SubInfo
    {
        uint64_t bev_session_id = 0;
        int32_t formular_id = 0; // 公式id
        uint16_t topic = 0;      // 订阅的主题



        
    };

    struct SubInfoBevSessionKey
    {
    };
    struct SubInfoBevSessionFormularIdKey
        : composite_key<SubInfo,
                        BOOST_MULTI_INDEX_MEMBER(SubInfo, uint64_t, bev_session_id),
                        BOOST_MULTI_INDEX_MEMBER(SubInfo, int32_t, formular_id)>
    {
    };
    struct SubInfoTopicHjcodeKey
        : composite_key<SubInfo,
                        BOOST_MULTI_INDEX_MEMBER(SubInfo, uint16_t, topic)>
    {
    };

    struct SubInfoFormularIdTopicHjcodeKey
        : composite_key<SubInfo,
                        BOOST_MULTI_INDEX_MEMBER(SubInfo, int32_t, formular_id),
                        BOOST_MULTI_INDEX_MEMBER(SubInfo, uint16_t, topic)>
    {
    };

    typedef boost::interprocess::allocator<SubInfo, boost::interprocess::managed_shared_memory::segment_manager> sub_info_allocator;
    typedef multi_index_container<
        SubInfo,
        indexed_by<hashed_non_unique<tag<SubInfoBevSessionKey>,
                                     BOOST_MULTI_INDEX_MEMBER(SubInfo, uint64_t, bev_session_id)>,
                   hashed_non_unique<SubInfoBevSessionFormularIdKey>,
                   hashed_non_unique<SubInfoTopicHjcodeKey>,
                   hashed_non_unique<SubInfoFormularIdTopicHjcodeKey>>,
        sub_info_allocator>
        SubInfoSet;

    typedef boost::interprocess::allocator<int, boost::interprocess::managed_shared_memory::segment_manager> shmem_vector_allocator;
    typedef boost::interprocess::vector<int, shmem_vector_allocator> my_vector;
    typedef boost::interprocess::allocator<boost::interprocess::string, boost::interprocess::managed_shared_memory::segment_manager> shmem_vector_string_allocator;
    typedef boost::interprocess::vector<boost::interprocess::string, shmem_vector_string_allocator> vector_string;

    typedef int key_type;
    typedef uint64_t mapped_type;
    typedef std::pair<const int, uint64_t> value_type;
    typedef boost::interprocess::allocator<value_type, boost::interprocess::managed_shared_memory::segment_manager> shmem_map_allocator;
    typedef boost::interprocess::map<key_type, mapped_type, std::less<key_type>, shmem_map_allocator> my_map;

    typedef boost::interprocess::allocator<value_type, boost::interprocess::managed_shared_memory::segment_manager> shmem_std_unordered_map_allocator;
    typedef boost::unordered_map<key_type, mapped_type, boost::hash<key_type>, std::equal_to<key_type>, shmem_std_unordered_map_allocator>
        my_std_unordered_map;

    custom_data();
    void init(boost::interprocess::managed_shared_memory &segment);

    void add();

    void push_back(int num);
    void push_back(std::string str);

    std::vector<uint64_t> pop_all();
    // std::vector<std::string> pop_all();

    void print();

private:
    int *a_ptr_ = nullptr;
    boost::interprocess::interprocess_mutex *a_mutex_ptr_ = nullptr;

    // my_vector *b_ptr_ = nullptr;
    my_std_unordered_map *b_ptr_ = nullptr;
    boost::interprocess::interprocess_mutex *b_mutex_ptr_ = nullptr;
    boost::interprocess::interprocess_condition *b_cond_ptr_ = nullptr;

    vector_string *v_s_ptr = nullptr;

    SubInfoSet *sub_info_set_ptr_ = nullptr;
};
